package com.example.springboot.config;

import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
 * springboot2.0自动集成lettuce,但可能会缺少commons-pool2依赖
 * <p>  当然可以通过手动配置LettuceConnectionFactory,这种情况下不需要引入commons-pool2依赖
 */

@Configuration
public class RedisConfig {

    /**
     * 手动配置LettuceConnectionFactory
     */
    //@Bean
    //RedisConnectionFactory factory(RedisProperties properties){
    //    LettuceConnectionFactory rcf = new LettuceConnectionFactory();
    //    rcf.setPort(properties.getPort());
    //    rcf.setHostName(properties.getHost());
    //    rcf.setPassword(properties.getPassword());
    //    rcf.setDatabase(properties.getDatabase());
    //    return rcf;
    //}

    /**
     *  把RedisTemplate 的泛型是 <Object,Object> 设置成 RedisTemplate<String,Object>，方便代码编写。
     *  RedisAutoConfiguration配置类中有@ConditionalOnMissingBean(name = "redisTemplate")条件，
     *  所以如果 Spring 容器中有一个 name 为 redisTemplate 的 RedisTemplate 对象那么这个自动配置的 RedisTemplate 就不会实例化，对其进行覆盖替换。
     */
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);


        // hash的key采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }


    /**
     *
     * 监听RedisKey过期事件
     * @return org.springframework.data.redis.listener.RedisMessageListenerContainer
     */
    @Bean
    @SuppressWarnings("all")
    RedisMessageListenerContainer listenerContainer(RedisConnectionFactory factory){
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        return container;
    }

}
